import javax.sound.sampled.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Chat extends JFrame implements ActionListener, Runnable {
    ObjectOutputStream m_out;
    ObjectInputStream m_in;

    private final AudioFormat FORMAT = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 1, 2, 44100, true);
    private final int BUFFER_SIZE = (int)(FORMAT.getFrameSize() * FORMAT.getFrameRate() / 2.0);

    private Sender m_sender;
    private Receiver m_receiver;
    
    private SoundPlayer m_soundPlayer;
    private SoundRecorder m_soundRecorder;

    private JTextArea m_messageArea;
    private JTextArea m_historyArea;

    private JButton m_sendButton;   
    
    private MessageQueue m_inputQueue;
    private MessageQueue m_outputQueue;
    
    private Thread thread;

    Chat(String title)
    {
        super(title);

        m_inputQueue = new MessageQueue();
        m_outputQueue = new MessageQueue();

        Container pane = getContentPane();
        pane.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();

        m_historyArea = new JTextArea();
        m_historyArea.setEditable(false);
        m_historyArea.setBorder(BorderFactory.createLineBorder(Color.black));

        c.weighty = 1.0;
        c.weightx = 1.0;
        c.fill = GridBagConstraints.BOTH;
        c.gridx = 0;  c.gridy = 0;
        c.gridwidth = GridBagConstraints.REMAINDER; c.gridheight = GridBagConstraints.RELATIVE;
        c.insets = new Insets(5,5,5,5);
        pane.add(m_historyArea, c);


        m_messageArea = new JTextArea();
        m_messageArea.setBorder(BorderFactory.createLineBorder(Color.black));
        c.fill = GridBagConstraints.BOTH;
        c.weighty = 0.5;
        c.weightx = 1.0;
        c.gridx = 0;  c.gridy = 1;
        c.gridwidth = GridBagConstraints.RELATIVE; c.gridheight = GridBagConstraints.REMAINDER;
        pane.add(m_messageArea, c);

        m_sendButton = new JButton("SEND");
        m_sendButton.addActionListener(this);
        c.fill = GridBagConstraints.BOTH;
        c.weighty = 0.5;
        c.weightx = 0.0;
        c.gridx = 1;  c.gridy = 1;
        c.gridwidth = GridBagConstraints.REMAINDER; c.gridheight = GridBagConstraints.REMAINDER;
        pane.add(m_sendButton, c);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
        setSize(200,250);
    }

    public void setIn(ObjectInputStream in)
    {
        m_in = in;
    }

    public void setOut(ObjectOutputStream out)
    {
        m_out = out;
    }

    public void actionPerformed(ActionEvent event)
    {
        byte[] message = m_messageArea.getText().getBytes();
        if (message.length > 0)
        {
            m_historyArea.append("ME> " + m_messageArea.getText() + "\n");
            m_messageArea.setText("");
            m_outputQueue.push(new Message(Message.TEXT, message, message.length));
        }
    }
    

    public void start()
    {
        m_soundPlayer = new SoundPlayer(FORMAT, BUFFER_SIZE);
        m_soundRecorder = new SoundRecorder(FORMAT, BUFFER_SIZE, m_outputQueue);
        m_sender = new Sender(m_out, m_outputQueue);
        m_receiver = new Receiver(m_in, m_inputQueue, BUFFER_SIZE);
        thread = new Thread(this);
        thread.start();

        //m_soundRecorder.setDaemon(true);
        m_soundRecorder.start();

        //m_sender.setDaemon(true);
        m_sender.start();

        //m_receiver.setDaemon(true);
        m_receiver.start();

    }

    public void stop()
    {
        thread.interrupt();
        m_sender.stop();
        m_receiver.stop();
    }

    public void run()
    {
        while (true)
        {
            //System.out.println("chat queue " + m_inputQueue.queue.size());
            if (!m_inputQueue.isEmpty())
            {
                Message message = m_inputQueue.get();
                m_inputQueue.pop();
                switch (message.type)
                {
                    case Message.TEXT:
                        m_historyArea.append("MY FRIEND> " + new String(message.data) + "\n");
                        break;
                    case Message.SOUND:
                        m_soundPlayer.play(message.data, message.length);
                        break;
                }
            }
            else
            {
                try
                {
                    thread.sleep(1);
                }
                catch (InterruptedException e)
                {
                    break;
                }
            }
        }
    }
    
    public void writeSystemMessage(String message)
    {
        m_historyArea.append("SYSTEM> " + message + "\n");
    }


}
